package com.kakavr.pay.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.util.ClassUtils;

import com.kakavr.base.log.BaseLog;
import com.kakavr.pay.constant.WxConstant;
import com.kakavr.util.ConvertUtils;

/**
 * http客户端公共类
 * @author gang.yang
 *
 */
public class HttpClientUtil extends BaseLog {

	/**
	 * 不需要证书的post请求
	 * @param url 请求的地址
	 * @param parameters 请求参数
	 * @return
	 * @throws IOException
	 */
	public static Map<String, Object> doPost(String url,
			Map<String, Object> parameters) throws IOException {
		sinfo("及时返回请求前的参数：" + parameters);
		StringEntity se = new StringEntity(ConvertUtils.toJson(parameters),
				ContentType.create("application/x-www-form-urlencoded",
						WxConstant.CHARSET));
		String result = exePost(url, se, null);
		return ConvertUtils.jsonToMap(result);
	}

	/**
	 * 不需要证书的post请求
	 * @param url 请求的地址
	 * @param xml 请求的参数
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> doPostByXML(String url, String xml)
			throws Exception {
		sinfo("执行及时返回请求前的参数：" + xml);
		StringEntity se = new StringEntity(xml, WxConstant.CHARSET);
		String result = exePost(url, se, null);
		sinfo("执行及时返回请求结果：" + result);
		return WXPayUtil.xmlToMap(result);
	}
	
	/**
	 * get请求
	 * @param url 请求地址
	 * @return
	 */
	public static Map<String, Object> doGet(String url){
		CloseableHttpClient httpclient = HttpClients.createDefault();
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String result = null;
		try {
			HttpGet get = new HttpGet(url);
			response = httpclient.execute(get);
			if (response != null) {
				StatusLine sl = response.getStatusLine();
				if (sl != null) {
					int statusCode = sl.getStatusCode();
					if (200 == statusCode) {
						entity = response.getEntity();
						if (entity != null) {
							result = EntityUtils.toString(entity,
									WxConstant.CHARSET);
						}
					}
				}
				return ConvertUtils.jsonToMap(result);
			}
		} catch (Exception e) {
			serror("执行及时通信返回请求出错，错误信息：" + e);
		}finally{
			try {
				EntityUtils.consume(entity);
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e1) {
			}
		}
		return null;
	}

	/**
	 * 加载证书的请求（微信转账时使用）
	 * @param url 请求地址
	 * @param xml 请求参数
	 * @param mchId 请求商户号
	 * @return
	 * @throws IOException
	 */
	public static Map<String, String> doSSLPostByXML(String url, String xml,
			String mchId) throws IOException {
		InputStream ksis = null;
		try {
			ksis = new FileInputStream(new File(ClassUtils
					.getDefaultClassLoader().getResource("apiclient_cert.p12")
					.getPath()));
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			keyStore.load(ksis, mchId.toCharArray());
			SSLContext sslcontext = SSLContexts.custom()
					.loadKeyMaterial(keyStore, mchId.toCharArray()).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
					sslcontext, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.getDefaultHostnameVerifier());
			StringEntity se = new StringEntity(xml, WxConstant.CHARSET);
			String result = exePost(url, se, sslsf);
			sinfo("执行分账返回请求结果：" + result);
			return WXPayUtil.xmlToMap(result);
		} catch (Exception e) {
			serror("执行分账出错，错误是：" + e);
		}finally{
			if(null != ksis){
				ksis.close();
			}
		}
		return null;
	}

	/**
	 * 执行post请求
	 * @param url 地址
	 * @param se 包装参数
	 * @param sslsf 证书链接
	 * @return
	 */
	private static String exePost(String url, StringEntity se,
			SSLConnectionSocketFactory sslsf) {
		CloseableHttpClient httpclient = null;
		if (null == sslsf) {
			httpclient = HttpClients.createDefault();
		} else {
			httpclient = HttpClients.custom().setSSLSocketFactory(sslsf)
					.build();
		}
		CloseableHttpResponse response = null;
		HttpEntity entity = null;
		String result = null;
		try {
			HttpPost post = new HttpPost(url);
			post.setEntity(se);
			response = httpclient.execute(post);
			if (response != null) {
				StatusLine sl = response.getStatusLine();
				if (sl != null) {
					int statusCode = sl.getStatusCode();
					if (200 == statusCode) {
						entity = response.getEntity();
						if (entity != null) {
							result = EntityUtils.toString(entity,
									WxConstant.CHARSET);
						}
					}
				}
			}
		} catch (Exception e) {
			serror("执行及时通信返回请求出错，错误信息：" + e);
		}finally{
			try {
				EntityUtils.consume(entity);
				if (response != null) {
					response.close();
				}
				httpclient.close();
			} catch (IOException e1) {
			}
		}
		return result;
	}

}
